﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Browser;
using SuperGo.Silverlight.WebApp;

namespace SuperGo.Silverlight {
	public partial class Page {
		readonly GoServicesSoapClient _service = GoService.GetGoServicesSoapClient();

		public WsPlayer CurrentPlayer { get; private set; }
		public string SessionKey { get; private set; }
		public string UserId { get; private set; }

		public Page() {
			try {
				InitializeComponent();
				Loaded += new RoutedEventHandler(Page_Loaded);
			} catch (Exception ex) {
				HandleException(ex);
			}
		}

		void Page_Loaded(object sender, RoutedEventArgs e) {
			try {
				Application.Current.UnhandledException += new EventHandler<ApplicationUnhandledExceptionEventArgs>(Current_UnhandledException);

				GetDataFromHostPage();

				_service.GetMovesOfGameSortedCompleted += new EventHandler<GetMovesOfGameSortedCompletedEventArgs>(service_GetMovesOfGameSortedCompleted);
				_service.CreateGameCompleted += new EventHandler<CreateGameCompletedEventArgs>(service_CreateGameCompleted);
				_service.GetCurrentPlayerCompleted += new EventHandler<GetCurrentPlayerCompletedEventArgs>(service_GetCurrentPlayerCompleted);
				_service.GetGoFriendsCompleted += new EventHandler<GetGoFriendsCompletedEventArgs>(service_GetGoFriendsCompleted);
				_service.GetActiveGamesCompleted += new EventHandler<GetActiveGamesCompletedEventArgs>(service_GetActiveGamesCompleted);
				_service.AcceptGameCompleted += new EventHandler<AcceptGameCompletedEventArgs>(service_AcceptGameCompleted);
				_service.RejectGameCompleted += new EventHandler<RejectGameCompletedEventArgs>(service_RejectGameCompleted);
				_service.CounterGameCompleted += new EventHandler<CounterGameCompletedEventArgs>(service_CounterGameCompleted);
				_service.WithdrawGameCompleted += new EventHandler<WithdrawGameCompletedEventArgs>(service_WithdrawalGameCompleted);
				_service.FinalizeGameCompleted += new EventHandler<FinalizeGameCompletedEventArgs>(service_FinalizeGameCompleted);
				_service.UpdateCurrentUserCompleted += new EventHandler<UpdateCurrentUserCompletedEventArgs>(service_UpdateCurrentUserCompleted);

				// get current user, then call other web services on completion
				_service.GetCurrentPlayerAsync(SessionKey, UserId);
			} catch (Exception ex) {
				HandleException(ex);
			}
		}

		public void FinalizeGame(int gameId, decimal blackScore, decimal whiteScore, int blackCaptures, int whiteCaptures) {
			ShowLoadingPage();
			_service.FinalizeGameAsync(gameId, blackScore, whiteScore, blackCaptures, whiteCaptures, CurrentPlayer, SessionKey, true);
			// goto service_FinalizeGameCompleted
		}

		void service_FinalizeGameCompleted(object sender, FinalizeGameCompletedEventArgs e) {
			string currentUserMessage = e.Result;
			ShowDialog("Game Over", currentUserMessage);
		}

		void service_GetCurrentPlayerCompleted(object sender, GetCurrentPlayerCompletedEventArgs e) {
			try {
				CurrentPlayer = e.Result;

				// the secret error message code
				if (CurrentPlayer.PlayerId == -1) {
					ShowDialog("An Error Occurred", CurrentPlayer.Name);
					return;
				}

				// get facebook friends
				_service.GetGoFriendsAsync(SessionKey, UserId);

				// get active go games
				_service.GetActiveGamesAsync(CurrentPlayer.PlayerId);
			} catch (Exception ex) {
				HandleException(ex);
			}
		}

		void service_GetActiveGamesCompleted(object sender, GetActiveGamesCompletedEventArgs e) {
			try {
				ShowContinueExistingGame(e.Result);
			} catch (Exception ex) {
				HandleException(ex);
			}
		}

		private void ShowPage(ControlPageBase controlToShow) {
			_gamePage.Show();
			_initiateGame.Hide();
			_continueExistingGame.Hide();
			_preferences.Hide();
			if (!_messageBox.ResultPending)
				_messageBox.Hide();
			_loading.Hide();

			controlToShow.Show();
		}

		private void ShowContinueExistingGame(ICollection<WsGame> activeGames) {
			if (activeGames.Count == 0) {
				ShowPage(_initiateGame);
			} else {
				_continueExistingGame.SetActiveGames(activeGames);
				ShowPage(_continueExistingGame);
			}
		}

		public void ShowPreferences() {
			_preferences.SetUser(CurrentPlayer);
			ShowPage(_preferences);
		}

		void service_GetGoFriendsCompleted(object sender, GetGoFriendsCompletedEventArgs e) {
			try {
				WsPlayer[] result = e.Result;
				IEnumerable<WsPlayer> allFriendsSorted = result.OrderBy(f => f.Name).ToList();
				_initiateGame.SetFriendsList(allFriendsSorted);
			} catch (Exception ex) {
				HandleException(ex);
			}
		}

		private void GetDataFromHostPage() {
			HtmlElement sessionKeyElement = HtmlPage.Document.GetElementById("sessionKeyHiddenField");
			HtmlElement userIdElement = HtmlPage.Document.GetElementById("userIdHiddenField");

			if (sessionKeyElement == null || userIdElement == null)
				throw new InvalidOperationException("The HTML form hosting the silverlight control must have both a 'sessionKeyHiddenField' field and a 'userIdHiddenField'.");

			SessionKey = sessionKeyElement.GetAttribute("value");
			UserId = userIdElement.GetAttribute("value");

			if (String.IsNullOrEmpty(SessionKey) || String.IsNullOrEmpty(UserId))
				throw new InvalidOperationException("The HTML form hosting has have both a 'sessionKeyHiddenField' field and a 'userIdHiddenField' but their values have not been set.");
		}

		void Current_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e) {
			HandleException(e.ExceptionObject);
		}

		void service_CreateGameCompleted(object sender, CreateGameCompletedEventArgs e) {
			WsGame wsGame = e.Result;
			_gamePage.StartGame(wsGame);
			ShowPage(_gamePage);
		}

		public void StartGame(WsGame newGame) {
			try {
				ShowLoadingPage();
				_service.CreateGameAsync(newGame, Page.CurrentPlayer, Page.SessionKey);

			} catch (Exception ex) {
				HandleException(ex);
			}
		}

		public void LoadGame(WsGame gameToLoad) {
			try {
				ShowLoadingPage();
				_gamePage.LoadGame(gameToLoad);
				_service.GetMovesOfGameSortedAsync(gameToLoad.GameId);
				// goto: service_GetMovesOfGameSortedCompleted
			} catch (Exception ex) {
				HandleException(ex);
			}
		}

		void service_GetMovesOfGameSortedCompleted(object sender, GetMovesOfGameSortedCompletedEventArgs e) {
			try {
				WsMove[] moves = e.Result;
				_gamePage.PlayMoves(moves);
				ShowPage(_gamePage);
			} catch (Exception ex) {
				HandleException(ex);
			}
		}

		public void DrawBoard(int size) {
			_gamePage.DrawBoard(size);
		}

		public void ShowLoadingPage() {
			ShowPage(_loading);
		}

		public void UpdatePreferences(WsPlayer wsPlayer) {
			ShowLoadingPage();
			_service.UpdateCurrentUserAsync(wsPlayer);
		}

		void service_UpdateCurrentUserCompleted(object sender, UpdateCurrentUserCompletedEventArgs e) {
			WsResultOfWsPlayer result = e.Result;
			if (result.Success) {
				CurrentPlayer = result.Result;
				ShowPage(_gamePage);
			} else {
				_preferences.ShowError(result.ErrorMessage);
				ShowPage(_preferences);
			}
		}

		public void ShowDialog(string title, string text) {
			ShowPage(_messageBox);
			_messageBox.Show(title, text);
		}

		public void ShowDialog(string title, string text, MessageBoxButtons messageBoxButtons, MessageBoxClosedDelegate messageBoxClosed) {
			ShowPage(_messageBox);
			_messageBox.Show(title, text, messageBoxButtons, messageBoxClosed);
		}

		public void ShowInitiateGame() {
			ShowPage(_initiateGame);
		}

		public void ShowContinueExistingGame() {
			_service.GetActiveGamesAsync(CurrentPlayer.PlayerId);
		}

		/// <summary>
		/// Use this version to display an initiate game request.
		/// </summary>
		/// <param name="wsGame"></param>
		public void ShowInitiateGame(WsGame wsGame) {
			_continueExistingGame.Hide();
			_initiateGame.Show(wsGame);
		}

		public void AcceptGame(WsGame _wsGame) {
			_gamePage.LoadGame(_wsGame);
			ShowPage(_loading);
			_service.AcceptGameAsync(_wsGame.GameId, CurrentPlayer, SessionKey);
		}

		void service_AcceptGameCompleted(object sender, AcceptGameCompletedEventArgs e) {
			WsMove[] moves = e.Result;
			_gamePage.PlayMoves(moves);
			ShowPage(_gamePage);
		}

		public void RejectGame(WsGame _wsGame) {
			ShowPage(_loading);
			_service.RejectGameAsync(_wsGame.GameId, CurrentPlayer, SessionKey);
		}

		private void service_RejectGameCompleted(object sender, RejectGameCompletedEventArgs e) {
			ShowContinueExistingGame(e.Result);
		}

		public void WithdrawRequest(WsGame wsGame) {
			ShowPage(_loading);
			_service.WithdrawGameAsync(wsGame.GameId, CurrentPlayer, SessionKey);
		}

		void service_WithdrawalGameCompleted(object sender, WithdrawGameCompletedEventArgs e) {
			ShowContinueExistingGame(e.Result);
		}

		public void CounterGame(WsGame counterOffer) {
			ShowPage(_loading);
			_service.CounterGameAsync(counterOffer, CurrentPlayer, SessionKey);
		}

		private void service_CounterGameCompleted(object sender, CounterGameCompletedEventArgs e) {
			WsGame wsGame = e.Result;
			_gamePage.StartGame(wsGame);
			ShowPage(_gamePage);
		}

		public void ShowGamePage() {
			ShowPage(_gamePage);
		}

		public bool LoggedInPlayerToMove() {
			return _gamePage.LoggedInPlayerToMove();
		}
	}
}
